Skip to content

test(types): re-derive and pin the WIDER ledger's #7760 pairs figure, amend #8222's stale live-figure guidance - #8575

Merged
os-sales merged 2 commits into
mainfrom
claude/issue-8458-parity-header-figures
Sep 8, 2026
Merged

test(types): re-derive and pin the WIDER ledger's #7760 pairs figure, amend #8222's stale live-figure guidance#8575
os-sales merged 2 commits into
mainfrom
claude/issue-8458-parity-header-figures

Conversation

@claude

@claude claude Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Fixes #8458
Fixes #8248

Two cards, one file, one branch — both are a claim in zod-mirror-parity.test.ts's own
prose that no instrument covers.

⭐ The durable finding: 16 was never right — it was never defined

The card, its triage and the dispatch all framed this as a figure that went stale when
PR #8354 moved the ledger. It did not go stale. 16 is neither reading of the word:
the move emptied 13 entries and touched 18, and no definition of "pairs" yields 16 at
either revision. Re-deriving it is what showed this — adopting the reviewer's 18 would have
produced the same corrected digit and left the actual defect in place.

So the class is not "a number rotted beside pinned neighbours". It is a number was
published with no definition, and this file's own reviewers reproduced it twice without
one
— the card's author, and the contract reviewer who measured 18 and reported it as a
correction rather than as an ambiguity. That is why step 3 of the card existed, and it is
why this PR writes a definition and a decomposition into the sentence instead of
correcting a digit: a corrected 18 with no definition forks again the first time someone
counts the emptied entries instead.

Card #8458 — the pairs figure

The count, and how it was derived

18. The sentence now reads 19 keys across **18** pairs LEFT (**13 emptied + 5 reduced = 18**).

⛔ Not adopted from the card or from triage — both said in as many words not to, and
neither had re-derived it. Method, in full:

  1. The transition the sentence describes is PR fix(types): give seven recursion-breaking zod mirrors their declaration as both type arguments #8354's, and the two trees either side of
    it are 645ecb98c (its parent) and a480f797a (its merge). Confirmed by reading the
    ledger's own pinned totals out of the file at each: **34 entries** … **52 keys** … **61 arms** before, **23 entries** … **36 keys** … **47 arms** after — exactly the
    two states the sentence names.
  2. The reader is this file's own ledgerEntryMembers('WiderThanDeclared'), not a
    re-implementation: the derivation script slices that function's source text out of the
    working-tree copy of the test file, transpiles it with ts.transpileModule, and calls
    it against each revision. So the instrument that sizes the ledger in CI is byte-identical
    to the one that sized it here. ⛔ Nothing was hand-reconciled.
  3. Diff the entry-to-key pairs:
BEFORE (645ecb98c): { entries: 34, keys: 52 }
AFTER  (a480f797a): { entries: 23, keys: 36 }
KEYS LEFT   : 19
KEYS ENTERED:  3
PAIRS that lost at least one key : 18
  of which EMPTIED (entry gone)  : 13
  of which REDUCED (entry stays) :  5
NEW entries in AFTER             :  2
CHECK entries: 34 - 13 emptied + 2 new = 23 (after=23)
CHECK keys   : 52 - 19 left  + 3 entered = 36 (after=36)

Both movements close against figures already pinned at those revisions, so the reading is
anchored on both sides rather than asserted. The 5 reduced entries are
AppComponentSchema, DashboardComponentSchema, PageNodeSchema, ObjectViewSchema,
DetailViewSchema.

16 is wrong under both readings of the word — 13 emptied, 18 touched. That is the
strongest argument for step 3 below: it was not a stale figure, it was an undefined one.

PR #8354's body needs no correction — it merged 2026-09-08, so the card's conditional
("if it has not merged") does not fire. Nothing was edited there.

(a) or (b): (a), pinned

headerFigures(/(\d+) of the registered pairs carry TYPE drift TODAY/) already pins a
pairs-shaped figure in this file, so this copies a precedent rather than opening one, and
the card's cost argument ("every pinned figure is a maintenance cost") is weaker than the
card assumed. The maintenance cost is also near zero because the figure is historical:
it is a reading of two fixed trees and cannot rot, so no future ledger move touches it.
Dropping it under (b) would have deleted the only statement of how big that move was — the
neighbouring It read 34 / 52 / 61 … sentences give the totals but not the shape of the
movement.

The pin is a new describe at the bottom of the file, deliberately not folded into the
objectui#8252 block: that one derives LIVE figures from the arms, and

nothing here compares the movement to the live ledger. WiderThanDeclared today is
neither of the two trees (objectui#8338 moved it again afterwards), and pointing a figure
at it would make the statement live, rot it on the next ledger move, and reintroduce the
hand re-derivation objectui#8243 removed. What is checked is the statement's internal
arithmetic
emptied + reduced == pairs, the restated total, and pairs <= keysLeft
(a touched pair contributed at least one of the keys that left) — plus non-vacuity legs so
an all-zero rewrite cannot satisfy it.

The definition of "pairs"

Written where the figure stands, because a number without one forks again:

pairs there counts every entry the move TOUCHED — an entry that lost a key and KEPT
others is still one it moved — and emptied is the subset that lost its whole content.

Both readings are now written down, which is why the decomposition (13 emptied + 5 reduced)
is in the sentence instead of a bare digit: the reader can see which quantity is which.

Card #8248 — the stale live in objectui#8222's exclusion note

Implemented as ruled (decision batch #71, 2026-09-07), not re-opened.

  • The rule is written once, in the file header: the LIVE/HISTORICAL split governs
    assertion messages too, judged per CLAUSE — a clause that RECORDS A MEASUREMENT is
    historical and ⛔ never rewritten by a later card; a clause that GIVES GUIDANCE is live,
    must be true now, and a later card may and must amend it, citing the card that moved it.

  • The guidance half is amended. ⚠️ ONE live figure in the header is deliberately NOT here loses the word live, and an ⚠️ AMENDED (objectui#8248 …) paragraph states that
    the seed decomposition is a HISTORICAL reading anchored at named revisions per
    objectui#8243, that it therefore carries none of a live figure's obligations, and that the
    action the word "live" sends a reader off to do — pin it, or exclude it afresh — is the
    wrong one.

  • The two record clauses are untouched, byte-identical, and named here explicitly:

    1. It needs each key's PROVENANCE and no ledger in this file records that, so nothing here can derive it.
    2. It is excluded in writing where it stands, which is the other half of objectui#8222 — every live figure in that header is pinned or excluded with its reason, and ⛔ a new one that is neither should not be added.

    ⛔ No digits were copied into the note: restating the decomposition there would have
    created the second unpinned copy the record clause exists to forbid.

Two companion edits inside the same sentence's radius

Both are the same claim as #8248's subject sentence, on the claimed file surface, and
leaving them would have produced exactly the "a stale copy survives beside a corrected one"
shape this file records. Neither is a new finding; flagging them for the reviewer:

  • The file header itself said Exactly one live figure is excluded rather than pinned
    about the same seed decomposition. Amended the same way (the word, plus one clause citing
    objectui#8243 / objectui#8248). Leaving it would have contradicted the rule three lines below it.
  • objectui#8243's own block comment said That note is left exactly as it stands, which
    objectui#8248 has now made false. Changed to the past tense with one clause recording the
    amendment. Its record clause — it is an assertion message objectui#8243 has no business editing — is untouched.

Gates

gate result
pnpm exec vitest run packages/types/src/__tests__/zod-mirror-parity.test.ts Test Files 1 passed (1) · Tests 32 passed (32)
pnpm --filter @object-ui/types type-check (tsc --noEmit + tsconfig.examples.json + tsconfig.test.json) VERDICT command-exit 0
tsc -p tsconfig.test.json --listFiles reads this file (proof it is judged; the build project excludes **/__tests__/**)
node scripts/check-control-bytes.mjs OK (scanned 6771 tracked text file(s))
node scripts/check-changeset-presence.mjs exit 0 — empty frontmatter accepted, "declared as releasing nothing"
pnpm check:published-tsconfig-exclude · check:unreferenced-sources · changeset:check · check:comment-mask-corpus exit 0 each
node scripts/check-governed-queue-guard.mjs --test THE-TWO-PATHS NOT GOVERNED — 2 path(s) checked against 5 governed surface(s)

Lint is a declared narrowing, measured, not skipped. eslint on the changed file: 1 file,
0 errors, 0 warnings (--format json, count read from the JSON). Population read from
eslint's own config via ESLint#isPathIgnored over git ls-files: 4518 of 4520 tracked
lintable-extension files are in scope for eslint .. Invariance: eslint.config.js sets no
parserOptions.project and no projectService, so type-aware linting is off and a one-file
diff cannot move the verdict on any untouched file. The full farm is CI's run.
All figures above are from the final commit, 234eeea92.

Reverse verification

Predicted direction: turns red. Run from the committed tree, restore proven by blob hash
and an empty git diff HEAD, with an EXIT INT TERM trap holding absolute paths.

  • Control (unmutated): green, and the new test is named in the verbose output —
    ✓ … the objectui#7760 movement figures reconcile with themselves (objectui#8458) > the pairs that move touched equal its emptied entries plus its reduced ones
  • M1 — the digit put back to 16 (the actual defect): on-disk proof removed-text count=0, injected-text count=1, blob b71bcb40… != HEAD 16c95033…
    Tests 1 failed | 31 passed, expected { decomposition: 18, …(2) } to deeply equal { decomposition: 16, …(2) }.
  • M2 — the decomposition reworded away: → the header spelling /\*\*(\d+) emptied \+ (\d+) reduced = (\d+)\*\*/ must occur exactly once … it occurs 0 times. A reword that drops the figure is red, not silently unpinned.
  • Restore after each leg and at trap: leg restored (blob == HEAD) /
    TRAP-RESTORE OK: blob matches HEAD and git diff HEAD is empty. Re-run in full against the
    final commit, so every hash above is that tree's.

One self-audit, worth the reviewer's eye

The first draft of the new prose restated the two pinned figures a second time, in the
sentence explaining the fork — a restatement no pin reaches, which is the objectui#7733
shape one line further in and precisely what this paragraph warns against. It was removed
before the branch was opened for review: the sentence now says 16 "is NEITHER of the two
readings above" and states in writing that they are ⛔ not restated as digits. The digits
appear exactly once each, inside the pinned spellings.

Merged origin/main — what was re-derived, and what is immune and why

origin/main at 57bad9b00 was merged in (a merge, ⛔ not a rebase); the branch was
behind independently of any sequencing. No conflict, and the reason is measurable rather
than asserted: git log f5cfbbd81..origin/main -- packages/types/src/__tests__/zod-mirror-parity.test.ts
is empty — nothing on main has touched this file since the branch's base. The file's
blob hash is 16c95033 on both sides of the merge.

Re-derived, not carried over. The two revision extracts were deleted and re-cut from
git, and the whole derivation re-executed on the merged tree:

  • The pairs movement is unchanged, byte-identical output: BEFORE (645ecb98c) {entries: 34, keys: 52},
    AFTER (a480f797a) {entries: 23, keys: 36}, 19 keys left, 3 entered, 18 pairs touched,
    13 emptied, 5 reduced, both arithmetic checks closing. The sliced instrument hashed
    identically (4355dcac9ccd), so the reader did not move either.
  • Why it is immune — argued, then confirmed. Every figure in that sentence is a reading
    of two fixed trees. 645ecb98c and a480f797a are immutable, so nothing landing on
    main afterwards can change what the ledger held there. That is exactly the objectui#8243
    property this PR leans on; re-running it is the confirmation, not the argument.
  • The file's live figures are the ones that could have moved, and they are not re-derived
    by hand here: the existing objectui#7733 / objectui#8222 / objectui#8252 pins compare them
    to the ledgers on every run, so the post-merge Tests 32 passed (32) is that comparison
    coming back green. Had main moved a ledger, those blocks would be red, not silent.
  • ⚠️ No figure moved, so there is no finding to report here. Had one moved, it would have
    been filed as a card, not absorbed into this PR.

Post-merge re-runs at 6d7d72a08: parity test Tests 32 passed (32); pnpm --filter @object-ui/types type-checkVERDICT command-exit 0; check-control-bytes OK (6777
tracked text files); check-changeset-presence exit 0; check-governed-queue-guard --test
NOT GOVERNED; eslint on the changed file 1 file / 0 errors / 0 warnings, against a
population of 4520 of 4522 tracked lintable files read from eslint's own config, still
with no parserOptions.project and no projectService. The reverse verification was re-run
in full against the merged HEAD; every hash in the section above is from that run.

Clause-② carrier check

node scripts/pm/check-clause2-carriers.mjs --pair 8575, run from /home/user/objectstack
as instructed, exits 2, and its own line says why: it reads objectstack-ai/objectstack
by default, where #8575 is a different pull request, so "the pair could not be formed, so
nothing about it was judged"
— ⛔ not a clearance, and ⛔ not a failure either. Pointed at
this repo, PM_SWEEP_REPO=objectstack-ai/objectui … --pair 8575 exits 0: both #8458 and
#8248 read as "the clause-② declaration is readable in the fixed spelling and both carriers
agree, and its diff carries no widening tell."

Release notes

.changeset/8458-parity-header-pairs-figure.md, empty frontmatter. The file is under
src/ so the presence gate counts it, but nothing published moves: the package build
tsconfig.json excludes **/__tests__/** and @object-ui/types' files is ["dist", …].

🤖 Generated with Claude Code

https://claude.ai/code/session_01CZY49skxUBYyJcdnTcYPrE


Generated by Claude Code

… amend #8222's stale live-figure guidance

objectui#8458 — `zod-mirror-parity.test.ts`'s header said the objectui#7760 move
took "19 keys across 16 pairs". Every other figure in that paragraph is read by a
`headerFigures` pin and moved correctly with PR #8354; the pairs figure was the one
no spelling reached, so it compiled and tested green while wrong.

Re-derived rather than adopted: this file's own `ledgerEntryMembers('WiderThanDeclared')`
was sliced out of the source, transpiled and run over the file at `645ecb98c` and
`a480f797a` (PR #8354's parent and its merge), diffing entry -> key pairs. 19 keys
left and 3 entered, across 18 distinct entries — 13 emptied, 5 reduced. Both
movements close against figures already pinned at those revisions (52 - 19 + 3 = 36
keys; 34 - 13 + 2 = 23 entries). `16` is neither reading.

The figure is now pinned, following the precedent of the "N of the registered pairs
carry TYPE drift TODAY" spelling already in this file, and "pairs" is defined where
it stands: every entry the move TOUCHED, with `emptied` as the subset that lost its
whole content. The pin reads only the sentence — the movement is a HISTORICAL
reading of two fixed trees, so nothing compares it to the live ledger.

objectui#8248 — objectui#8222's exclusion note still called the seed decomposition a
LIVE figure, which objectui#8243 made historical. Per the maintainer ruling (decision
batch #71) the guidance clause is amended and the two measurement-record clauses are
untouched; the record-vs-guidance rule is written once, in the file header.

Test-only: the file is under `__tests__/`, excluded by the package build tsconfig
and absent from its published `files`. Declared with an empty-frontmatter changeset.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CZY49skxUBYyJcdnTcYPrE
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3475.6 KB 3512.7 KB
Main entry chunk (gzip) 143.9 KB 350 KB
Entry file index-BH00rO6J.js
Status PASS

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 15.67KB 5.75KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 498.93KB 114.12KB
core (index.js) 7.48KB 2.96KB
create-plugin (index.js) 10.12KB 3.28KB
data-objectstack (index.js) 192.72KB 53.55KB
fields (index.js) 243.24KB 61.42KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 6.57KB 2.76KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.84KB 10.94KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 11.71KB 4.29KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 5.12KB 1.74KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 15.16KB 3.68KB
plugin-calendar (index.js) 49.00KB 13.91KB
plugin-charts (index.js) 71.39KB 19.92KB
plugin-chatbot (index.js) 194.53KB 46.34KB
plugin-dashboard (index.js) 131.43KB 34.44KB
plugin-designer (index.js) 213.21KB 43.63KB
plugin-detail (index.js) 248.46KB 63.90KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 131.01KB 32.32KB
plugin-gantt (index.js) 167.16KB 40.99KB
plugin-grid (index.js) 208.30KB 56.63KB
plugin-kanban (index.js) 55.40KB 15.71KB
plugin-list (index.js) 112.74KB 27.70KB
plugin-map (index.js) 20.49KB 6.83KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 30.10KB 8.74KB
plugin-tree (index.js) 9.33KB 3.25KB
plugin-view (index.js) 84.54KB 20.84KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.55KB 2.45KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 13.64KB 4.59KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

Brings the branch up to date after #8569, #8574 and the rest landed. No conflict:
nothing on main touched packages/types/src/__tests__/zod-mirror-parity.test.ts since
this branch's base f5cfbbd, so the objectui#8458 pin and the objectui#8248 amendment
compose with main rather than contending with it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CZY49skxUBYyJcdnTcYPrE
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3475.6 KB 3512.7 KB
Main entry chunk (gzip) 143.9 KB 350 KB
Entry file index-BH00rO6J.js
Status PASS

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 15.67KB 5.75KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 498.93KB 114.12KB
core (index.js) 7.48KB 2.96KB
create-plugin (index.js) 10.12KB 3.28KB
data-objectstack (index.js) 192.72KB 53.55KB
fields (index.js) 243.24KB 61.42KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 6.57KB 2.76KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.84KB 10.94KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 11.71KB 4.29KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 5.12KB 1.74KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 15.16KB 3.68KB
plugin-calendar (index.js) 49.00KB 13.91KB
plugin-charts (index.js) 71.39KB 19.92KB
plugin-chatbot (index.js) 194.53KB 46.34KB
plugin-dashboard (index.js) 131.43KB 34.44KB
plugin-designer (index.js) 213.21KB 43.63KB
plugin-detail (index.js) 248.46KB 63.90KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 131.01KB 32.32KB
plugin-gantt (index.js) 167.16KB 40.99KB
plugin-grid (index.js) 208.30KB 56.63KB
plugin-kanban (index.js) 55.40KB 15.71KB
plugin-list (index.js) 112.74KB 27.70KB
plugin-map (index.js) 20.49KB 6.83KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 30.10KB 8.74KB
plugin-tree (index.js) 9.33KB 3.25KB
plugin-view (index.js) 84.54KB 20.84KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.55KB 2.45KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 13.64KB 4.59KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@os-sales
os-sales marked this pull request as ready for review September 8, 2026 14:13

os-sales commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Landing checks ①②③ all satisfied — marked ready for review

Dispatching seat, session_01CZY49skxUBYyJcdnTcYPrE. Head 6d7d72a08.

check result
① in-seat contract review not required. Path limb clean — the diff touches packages/types/src/__tests__/zod-mirror-parity.test.ts and .changeset/, ⛔ no packages/spec/src/** and no *.zod.ts. Declaration limb: Clause-②: no on both carriers.
check-clause2-carriers --pair 8575 exit 0 — both #8458 and #8248 read as "the clause-② declaration is readable in the fixed spelling and both carriers agree, and its diff carries no widening tell."
③ CI + mergeability green — check suite completed on 6d7d72a08 with no failures; mergeable_state: clean against base 57bad9b00.

⚠️ On ② — read the exit code with the repo named. Run bare from /home/user/objectstack the script exits 2, because it defaults to reading objectstack-ai/objectstack, where #8575 is a different pull request. Its own line says "the pair could not be formed, so nothing about it was judged" — ⛔ that is not a clearance and ⛔ not a failure. The exit 0 above is with PM_SWEEP_REPO=objectstack-ai/objectui. The dev reported both readings rather than the convenient one, which is the reason this distinction is on the record at all.

Sequencing, already ruled and now discharged. This PR was originally held behind PR #8501 (same file). That hold was reversed: its only purpose was to spare #8501's contract review a re-run on a moved head, and #8501 has since gone BLOCK on a maintainer ruling, so its head must move and its review must re-run regardless. #8501 merges origin/main after this lands. ⚠️ Nothing on main has touched this file since f5cfbbd81 (git log over that path across the range is empty), so the composition there should be clean.

Declared, ⛔ not buried: the dev self-reported one --force-with-lease on its own feature branch before this PR existed — no other actor's work and no PR or review state existed on the branch at that moment, and no force-push has happened since. The standing rule bans force-push outright; recording it here rather than letting it pass silently.

⛔ This seat does not merge, and it has ⛔ not guessed a merge method or enabled auto-merge — the merge itself is the queue's and the maintainer's. Marked ready for review; everything gating it is green.


Generated by Claude Code

@os-sales
os-sales added this pull request to the merge queue Sep 8, 2026
Merged via the queue into main with commit d02942b Sep 8, 2026
35 checks passed
@os-sales
os-sales deleted the claude/issue-8458-parity-header-figures branch September 8, 2026 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment